{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Required boilerplate\n",
    "import sys\n",
    "!{sys.executable} -m pip install pytest\n",
    "!{sys.executable} -m pip install ipytest\n",
    "\n",
    "import ipytest.magics\n",
    "import pytest\n",
    "\n",
    "__file__ = 'testing2_exercise.ipynb'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Finalize test cases\n",
    "The testing part of the `TodoList` implementation is incomplete. Fill `____` parts of the tests. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "editable": false
   },
   "outputs": [],
   "source": [
    "class TodoNotFound(Exception):\n",
    "    pass\n",
    "\n",
    "\n",
    "class TodoList:\n",
    "    def __init__(self):\n",
    "        self._todo = {}\n",
    "        self._done = {}\n",
    "        self._task_counter = 1\n",
    "\n",
    "    @property\n",
    "    def todo_tasks(self):\n",
    "        return self._todo\n",
    "\n",
    "    @property\n",
    "    def done_tasks(self):\n",
    "        return self._done\n",
    "\n",
    "    def add(self, task):\n",
    "        self._todo[self._task_counter] = task\n",
    "        self._task_counter += 1\n",
    "\n",
    "    def complete(self, number):\n",
    "        if number not in self._todo:\n",
    "            raise TodoNotFound('{} not in todos'.format(number))\n",
    "\n",
    "        task = self._todo.pop(number)\n",
    "        self._done[number] = task\n",
    "\n",
    "    def remove(self, number):\n",
    "        if number not in self._todo:\n",
    "            raise TodoNotFound('{} not in todos'.format(number))\n",
    "\n",
    "        del self._todo[number]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finalize tests for `TodoList`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%run_pytest[clean]\n",
    "\n",
    "\n",
    "@pytest.____\n",
    "def todo_list():\n",
    "    tl = TodoList()\n",
    "    tl.add('buy milk')\n",
    "    tl.add('take dog out')\n",
    "    tl.add('learn pytest fixtures')\n",
    "    ____ ____\n",
    "\n",
    "\n",
    "def test_todo_tasks_property(todo_list):\n",
    "    todo = todo_list.todo_tasks\n",
    "    assert todo == {\n",
    "        1: 'buy milk',\n",
    "        2: 'take dog out',\n",
    "        3: 'learn pytest fixtures'\n",
    "    }\n",
    "\n",
    "\n",
    "def test_add(____):\n",
    "    todo_list.add('check pytest docs')\n",
    "    todos = todo_list.todo_tasks\n",
    "    assert todos[4] == ____\n",
    "\n",
    "\n",
    "def test_complete(todo_list):\n",
    "    # Make sure there is not done tasks yet\n",
    "    assert not todo_list.done_tasks\n",
    "\n",
    "    todo_list.complete(3)\n",
    "    done = todo_list.____\n",
    "    todo = todo_list.____\n",
    "    assert done[3] == 'learn pytest fixtures'\n",
    "    assert 3 not in ____\n",
    "\n",
    "\n",
    "def test_complete_with_unknown_task_number(todo_list):\n",
    "    # This is how you can test that a certain exception is raised\n",
    "    with pytest.raises(TodoNotFound):\n",
    "        todo_list.complete(10)\n",
    "\n",
    "\n",
    "def test_remove(todo_list):\n",
    "    todo_list.remove(1)\n",
    "    done = todo_list.done_tasks\n",
    "    todo = todo_list.todo_tasks\n",
    "\n",
    "    assert 1 not in ____\n",
    "    # Make sure it was not moved to done\n",
    "    ____ not done\n",
    "\n",
    "\n",
    "def test_remove_with_unknown_task_number(todo_list):\n",
    "    with pytest.____(____):\n",
    "        todo_list.remove(12)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Testing the [Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number)\n",
    "\n",
    "Implement a test for the `fibonacci` function. Use `pytest.mark.parametrize` and test at least with numbers: 0, 1, 2, 3, and 10. You can find the expected results and more information about the Fibonacci numbers [here](https://en.wikipedia.org/wiki/Fibonacci_number)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "editable": false
   },
   "outputs": [],
   "source": [
    "def fibonacci(number):\n",
    "    if number in [0, 1]:\n",
    "        return number\n",
    "    return fibonacci(number - 1) + fibonacci(number - 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%run_pytest[clean]\n",
    "\n",
    "# Your implementation here\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
